#pragma once

#include <jlib/jlib.h>
#include <GLFW/glfw3.h>
#include <map>


struct GLFWwindow;

struct Window {

  Window ();

  void show (int w, int h, const char* name);

  virtual ~Window ();
  virtual jlib::Ptr<jlib::RootNode> initRootNode () = 0;

private:
  void createWindow (int w, int h, const char* name);
  void destroyWindow ();

  static void initialize () ;
  static void onError (int error, const char* description);
  static void onWindowPos (GLFWwindow* window, int xpos, int ypos);
  static void onWindowSize (GLFWwindow* window, int width, int height);
  static void onWindowClose (GLFWwindow* window);
  static void onWindowFocus (GLFWwindow* window, int focused);
  static void onWindowIconify (GLFWwindow* window, int iconified);
  static void onFramebufferSize (GLFWwindow* window, int width, int height);
  static void onMouseButton (GLFWwindow* window, int button, int action, int mods);
  static void onCursorPos (GLFWwindow* window, double xpos, double ypos);
  static void onCursorEnter (GLFWwindow* window, int entered);
  static void onScroll (GLFWwindow* window, double xoffset, double yoffset);
  static void onKey (GLFWwindow* window, int key, int scancode, int action, int mods);
  static void onChar (GLFWwindow* window, unsigned int codepoint);

  GLFWwindow* _window = nullptr;
  jlib::Ptr<jlib::RootNode> _root = nullptr;
  jlib::Vec2 _lastPointerLocation = {0, 0};
  int _w = 0;
  int _h = 0;

  static bool __glfwInitialized;
  static std::unordered_map<GLFWwindow*, Window*> __windows;
  static jlib::KeyCode __keyMapping[GLFW_KEY_LAST + 1];
  static jlib::MouseButton __mouseButtonMapping[GLFW_MOUSE_BUTTON_LAST + 1];
};
